package de.umr.fb12.vs.os;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

 class IRQController {

	// per cpu irq lock
	Semaphore lock = new Semaphore(1);
	// wait for irq handler lock
	Semaphore active_irq = new Semaphore(0, true);
	// virtual timer service
	private Timer timer;
	// cpu this irq belongs to
	private final CPU cpu;
	// active irq
	// tickrate in ms
	static int tick_rate = 150;

	volatile int IRQ_type;
	volatile Object dev;

	IRQController(final CPU cpu) {
		timer = new Timer();
		this.cpu = cpu;
		try {
			// no irqs at startup
			lock.acquire();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// until implemented i/o apic and lapic only tick on first cpu
		if (cpu.cpuid == 0)
			timer.scheduleAtFixedRate(new TimerTask() {
				@Override
				public void run() {
					try {
						// get local irq lock
						lock.acquire();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					// set irq type
					IRQ_type = 0x00;
					// tell cpu there is one
					cpu.raiselocalIRQ();
					try {
						// wait for served irq on cpu
						while (!active_irq
								.tryAcquire(10, TimeUnit.MILLISECONDS))
							cpu.wakeUpIDLE();// FIXME find a better solution
												// than this hack
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					lock.release();

				}

			}, 0, tick_rate);
	}

	void start_async_io(final Task task, long time) {
		// implementet vio via later raised irq
		// same procedure as ticks but occurs only once after time in ms
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				try {
					lock.acquire();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// process.state = 0x01;
				IRQ_type = 1;
				dev = task;
				cpu.raiselocalIRQ();
				try {
					// wait for served irq on cpu
					while (!active_irq.tryAcquire(10, TimeUnit.MILLISECONDS))
						System.out.println("wakeup");
						cpu.wakeUpIDLE(); // FIXME find a better solution than
											// this hack
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				lock.release();
			}

		}, time);
	}

}
